/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 *                                                                  *
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
 * by the XIPHOPHORUS Company http://www.xiph.org/                  *
 *                                                                  *
 ********************************************************************

 function: basic shared codebook operations
 last mod: $Id: codebook.h,v 1.13 2002/06/28 22:19:35 xiphmont Exp $

 ********************************************************************/

#ifndef _V_CODEBOOK_H_
#define _V_CODEBOOK_H_

#include "../ogg/ogg.h"

/* This structure encapsulates huffman and VQ style encoding books; it
   doesn't do anything specific to either.

   valuelist/quantlist are nonNULL (and q_* significant) only if
   there's entry->value mapping to be done.

   If encode-side mapping must be done (and thus the entry needs to be
   hunted), the auxiliary encode pointer will point to a decision
   tree.  This is true of both VQ and huffman, but is mostly useful
   with VQ.

*/

typedef struct static_codebook
{
	long   dim;            /* codebook dimensions (elements per vector) */
	long   entries;        /* codebook entries */
	long*  lengthlist;     /* codeword lengths in bits */

	/* mapping ***************************************************************/
	int    maptype;        /* 0=none
			    1=implicitly populated values from map column
			    2=listed arbitrary values */

	/* The below does a linear, single monotonic sequence mapping. */
	long     q_min;       /* packed 32 bit float; quant value 0 maps to minval */
	long     q_delta;     /* packed 32 bit float; val 1 - val 0 == delta */
	int      q_quant;     /* bits: 0 < quant <= 16 */
	int      q_sequencep; /* bitflag */

	long*     quantlist;  /* map == 1: (int)(entries^(1/dim)) element column map
			   map == 2: list of dim*entries quantized entry vals
			*/

	/* encode helpers ********************************************************/
	struct encode_aux_nearestmatch* nearest_tree;
	struct encode_aux_threshmatch*  thresh_tree;
	struct encode_aux_pigeonhole*  pigeon_tree;

	int allocedp;
} static_codebook;

/* this structures an arbitrary trained book to quickly find the
   nearest cell match */
typedef struct encode_aux_nearestmatch
{
	/* pre-calculated partitioning tree */
	long*   ptr0;
	long*   ptr1;

	long*   p;         /* decision points (each is an entry) */
	long*   q;         /* decision points (each is an entry) */
	long   aux;        /* number of tree entries */
	long   alloc;
} encode_aux_nearestmatch;

/* assumes a maptype of 1; encode side only, so that's OK */
typedef struct encode_aux_threshmatch
{
	float* quantthresh;
	long*   quantmap;
	int     quantvals;
	int     threshvals;
} encode_aux_threshmatch;

typedef struct encode_aux_pigeonhole
{
	float min;
	float del;

	int  mapentries;
	int  quantvals;
	long* pigeonmap;

	long fittotal;
	long* fitlist;
	long* fitmap;
	long* fitlength;
} encode_aux_pigeonhole;

typedef struct codebook
{
	long dim;           /* codebook dimensions (elements per vector) */
	long entries;       /* codebook entries */
	long used_entries;  /* populated codebook entries */
	const static_codebook* c;

	/* for encode, the below are entry-ordered, fully populated */
	/* for decode, the below are ordered by bitreversed codeword and only
	   used entries are populated */
	float*        valuelist;  /* list of dim*entries actual entry values */
	ogg_uint32_t* codelist;   /* list of bitstream codewords for each entry */

	int*          dec_index;  /* only used if sparseness collapsed */
	char*         dec_codelengths;
	ogg_uint32_t* dec_firsttable;
	int           dec_firsttablen;
	int           dec_maxlength;

} codebook;

extern void vorbis_staticbook_clear( static_codebook* b );
extern void vorbis_staticbook_destroy( static_codebook* b );
extern int vorbis_book_init_encode( codebook* dest, const static_codebook* source );
extern int vorbis_book_init_decode( codebook* dest, const static_codebook* source );
extern void vorbis_book_clear( codebook* b );

extern float* _book_unquantize( const static_codebook* b, int n, int* map );
extern float* _book_logdist( const static_codebook* b, float* vals );
extern float _float32_unpack( long val );
extern long   _float32_pack( float val );
extern int  _best( codebook* book, float* a, int step );
extern int _ilog( unsigned int v );
extern long _book_maptype1_quantvals( const static_codebook* b );

extern int vorbis_book_besterror( codebook* book, float* a, int step, int addmul );
extern long vorbis_book_codeword( codebook* book, int entry );
extern long vorbis_book_codelen( codebook* book, int entry );



extern int vorbis_staticbook_pack( const static_codebook* c, oggpack_buffer* b );
extern int vorbis_staticbook_unpack( oggpack_buffer* b, static_codebook* c );

extern int vorbis_book_encode( codebook* book, int a, oggpack_buffer* b );
extern int vorbis_book_errorv( codebook* book, float* a );
extern int vorbis_book_encodev( codebook* book, int best, float* a,
								oggpack_buffer* b );

extern long vorbis_book_decode( codebook* book, oggpack_buffer* b );
extern long vorbis_book_decodevs_add( codebook* book, float* a,
									  oggpack_buffer* b, int n );
extern long vorbis_book_decodev_set( codebook* book, float* a,
									 oggpack_buffer* b, int n );
extern long vorbis_book_decodev_add( codebook* book, float* a,
									 oggpack_buffer* b, int n );
extern long vorbis_book_decodevv_add( codebook* book, float** a,
									  long off, int ch,
									  oggpack_buffer* b, int n );



#endif
